// Cell names have been changed in this file by netl_namemap on Mon Jan  3 04:00:11 UTC 2022
////////////////////////////////////////////////////////////////////////////// 
//
//  pcs_raw_ext_arbt_ctl.v
//
//  Control interface between external CREG and Arbiters (Memory and Register)
//
//  Original Author: Ameer Youssef 
//  Current Owner: Ameer Youssef   
//
////////////////////////////////////////////////////////////////////////////// 
//
// Copyright (C) 2013 Synopsys, Inc.  All rights reserved.
//
// SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of
// Synopsys, Inc., and is fully protected under copyright and trade secret
// laws.  You may not view, use, disclose, copy, or distribute this file or
// any information contained herein except pursuant to a valid written
// license agreement. It may not be used, reproduced, or disclosed to others
// except in accordance with the terms and conditions of that agreement.
//
////////////////////////////////////////////////////////////////////////////// 
//
//    Perforce Information
//    $Author: spagnuol $
//    $File: //dwh/up16/main/dev/pcs_raw/dig/rtl/pcs_raw_ext_arbt_ctl.v $
//    $DateTime: 2015/12/23 11:47:04 $
//    $Revision: #9 $
//
////////////////////////////////////////////////////////////////////////////// 

`include "dwc_e12mp_phy_x4_ns_cr_macros.v"
`include "dwc_e12mp_phy_x4_ns_pcs_raw_macros.v"

`timescale 1ns/10fs
module dwc_e12mp_phy_x4_ns_pcs_raw_ext_arbt_ctl (
// CR External Clock and reset
input  wire          cr_ext_clk,
input  wire          cr_ext_clk_rst,

// Clock and reset
input  wire          cr_clk,
input  wire          cr_rst,

// External CR control bus
input  wire [15:0]   cr_ext_addr,
input  wire [15:0]   cr_ext_wr_data,
input  wire          cr_ext_wr_en,
input  wire          cr_ext_rd_en,
output reg  [15:0]   cr_ext_rd_data,
output reg           cr_ext_ack,

input  wire          scan_mode,
input  wire          scan_set_rst,
  
// CR control bus with the Memory arbiter
output wire          cr_mem_req,
output wire [15:0]   cr_mem_addr,
output wire [15:0]   cr_mem_wr_data,
output wire          cr_mem_wr_en,
output wire          cr_mem_rd_en,
input  wire          cr_mem_ack,
input  wire [15:0]   cr_mem_rd_data,
  
// CR control bus with the Register arbiter
output wire          cr_reg_req,
output wire [15:0]   cr_reg_addr,
output wire [15:0]   cr_reg_wr_data,
output wire          cr_reg_wr_en,
output wire          cr_reg_rd_en,
input  wire          cr_reg_ack,
input  wire [15:0]   cr_reg_rd_data
);

// -------------------------
// Registers and nets
// -------------------------

wire        wr_en_pulse;
wire        rd_en_pulse;
wire        req_pulse;
wire        mem_sel;
wire        ack_int;
reg  [15:0] addr_int;
reg  [15:0] wr_data_int;
reg         req_int;
reg         wr_en_int;
reg         rd_en_int;
reg  [15:0] rd_data_int;
reg         rd_ack_int_d0;
reg         wr_ack_int_d0;
wire        rd_ack_pulse;
wire        wr_ack_pulse;

// Mantis 7185 - Add hand-instantiated muxes on cr_ext_addr,
// cr_ext_wr_data, and cr_ext_rd_data
wire [15:0] cr_ext_addr_mux;
wire [15:0] cr_ext_wr_data_mux;
wire [15:0] cr_ext_rd_data_mux;

// catch a wr_en pulse
dwc_e12mp_phy_x4_ns_gen_pcatch catch_wr_en (
  .q               (wr_en_pulse),
  .rst             (cr_rst),
  .clk             (cr_clk),
  .scan_mode_i     (scan_mode),
  .scan_set_rst_i  (scan_set_rst),
  .d               (cr_ext_wr_en)
);

// catch a rd_en pulse
dwc_e12mp_phy_x4_ns_gen_pcatch catch_rd_en (
  .q               (rd_en_pulse),
  .rst             (cr_rst),
  .clk             (cr_clk),
  .scan_mode_i     (scan_mode),
  .scan_set_rst_i  (scan_set_rst),
  .d               (cr_ext_rd_en)
);

assign req_pulse = wr_en_pulse | rd_en_pulse;

// Mantis 7185 - Add hand-instantiated muxes on cr_ext_addr,
// cr_ext_wr_data, and cr_ext_rd_data
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(16)) cr_ext_addr_gen_mux (
  .out (cr_ext_addr_mux),
  .sel (req_pulse),
  .d0  (addr_int),
  .d1  (cr_ext_addr)
);

dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(16)) cr_ext_wr_data_gen_mux (
  .out (cr_ext_wr_data_mux),
  .sel (req_pulse),
  .d0  (wr_data_int),
  .d1  (cr_ext_wr_data)
);

always @ (posedge cr_clk or posedge cr_rst) begin
  if (cr_rst) begin
    addr_int    <= 16'd0;
    wr_data_int <= 16'd0;
    req_int     <= 1'b0;
    wr_en_int   <= 1'b0;
    rd_en_int   <= 1'b0;
    rd_data_int <= 16'd0;
    rd_ack_int_d0 <= 1'b0;
    wr_ack_int_d0 <= 1'b0;
  end
  else begin
    addr_int    <= cr_ext_addr_mux;    // update addr with req_pulse
    wr_data_int <= cr_ext_wr_data_mux; // update wr_data with wr_en_pulse
    wr_en_int   <= (wr_en_pulse | wr_en_int) & ~ack_int; // sticky posedge detection, reset with ack
    rd_en_int   <= (rd_en_pulse | rd_en_int) & ~ack_int; // sticky posedge detection, reset with ack
    req_int     <= (  req_pulse |   req_int) & ~ack_int; // sticky posedge detection, reset with ack
    rd_data_int <= (ack_int & rd_en_int) ? (mem_sel ? cr_mem_rd_data : cr_reg_rd_data) : rd_data_int; // update read data with ack
    rd_ack_int_d0 <= ack_int & rd_en_int;
    wr_ack_int_d0 <= ack_int & wr_en_int;
  end
end

assign mem_sel = (addr_int[`DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_RANGE] == `DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_ROM0) |
                 (addr_int[`DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_RANGE] == `DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_ROM1) |
                 (addr_int[`DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_RANGE] == `DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_RAM0) |
                 (addr_int[`DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_RANGE] == `DWC_E12MP_X4NS_CR_TYPE_RAW_PCS_RAM1);

// Set outputs to Memory arbiter
assign cr_mem_req     = req_int & mem_sel; // only req needs to be qualified
assign cr_mem_addr    = addr_int;
assign cr_mem_wr_data = wr_data_int;
assign cr_mem_wr_en   = wr_en_int;
assign cr_mem_rd_en   = rd_en_int;

// Set outputs to Register arbiter
assign cr_reg_req     = req_int & ~mem_sel; // only req needs to be qualified
assign cr_reg_addr    = addr_int;
assign cr_reg_wr_data = wr_data_int;
assign cr_reg_wr_en   = wr_en_int;
assign cr_reg_rd_en   = rd_en_int;

// OR acks from arbiters
assign ack_int = cr_mem_ack | cr_reg_ack;

// catch a read ack pulse into cr_ext_clk domain
dwc_e12mp_phy_x4_ns_gen_pcatch catch_rd_ack_en (
  .q               (rd_ack_pulse),
  .rst             (cr_ext_clk_rst),
  .clk             (cr_ext_clk),
  .scan_mode_i     (scan_mode),
  .scan_set_rst_i  (scan_set_rst),
  .d               (rd_ack_int_d0)
);

// catch a write ack pulse into cr_ext_clk domain
dwc_e12mp_phy_x4_ns_gen_pcatch catch_wr_ack_en (
  .q               (wr_ack_pulse),
  .rst             (cr_ext_clk_rst),
  .clk             (cr_ext_clk),
  .scan_mode_i     (scan_mode),
  .scan_set_rst_i  (scan_set_rst),
  .d               (wr_ack_int_d0)
);

// Mantis 7185 - Add hand-instantiated muxes on cr_ext_addr,
// cr_ext_wr_data, and cr_ext_rd_data
dwc_e12mp_phy_x4_ns_gen_mux #(.WIDTH(16)) cr_ext_rd_data_gen_mux (
  .out (cr_ext_rd_data_mux),
  .sel (rd_ack_pulse),
  .d0  (cr_ext_rd_data),
  .d1  (rd_data_int)
);

// Flop read data into cr_ext_clk domain
// and produce ack for wr/rd operation
always @ (posedge cr_ext_clk or posedge cr_ext_clk_rst) begin
  if (cr_ext_clk_rst) begin
    cr_ext_rd_data <= 16'd0;
    cr_ext_ack <= 1'b0;
  end
  else begin
    cr_ext_rd_data <= cr_ext_rd_data_mux;
    cr_ext_ack <= rd_ack_pulse | wr_ack_pulse;
  end
end

endmodule

